package com.huiminpay.transaction.service;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.huiminpay.common.cache.domain.CommonErrorCode;
import com.huiminpay.common.cache.exception.BusinessCast;
import com.huiminpay.common.cache.exception.BusinessException;
import com.huiminpay.common.cache.util.RedisUtil;
import com.huiminpay.transaction.api.PayChannelServiceApi;
import com.huiminpay.transaction.api.dto.PayChannelDTO;
import com.huiminpay.transaction.api.dto.PayChannelParamDTO;
import com.huiminpay.transaction.api.dto.PlatformChannelDTO;
import com.huiminpay.transaction.common.util.RedisCache;
import com.huiminpay.transaction.convert.PayChannelParamConvert;
import com.huiminpay.transaction.convert.PlatformChannelConvert;
import com.huiminpay.transaction.entity.AppPlatformChannel;
import com.huiminpay.transaction.entity.PayChannelParam;
import com.huiminpay.transaction.entity.PlatformChannel;
import com.huiminpay.transaction.mapper.AppPlatformChannelMapper;
import com.huiminpay.transaction.mapper.PayChannelParamMapper;
import com.huiminpay.transaction.mapper.PlatformChannelMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @Author: HWW
 * @Date: 2021/8/2417:10
 * @Desc:
 */
@Service
@Slf4j
public class PayChannelService implements PayChannelServiceApi {

    @Autowired
    private PlatformChannelMapper platformChannelMapper;

    @Autowired
    private PayChannelParamMapper payChannelParamMapper;

    @Autowired
    private AppPlatformChannelMapper appPlatformChannelMapper;

    @Autowired
    private RedisCache cache;

    //查询惠民平台的服务类型
    @Override
    public List<PlatformChannelDTO> queryPlatformChannel() throws BusinessException {
        List<PlatformChannel> platformChannels = platformChannelMapper.selectList(null);

        return PlatformChannelConvert.INSTANCE.listentity2listdto(platformChannels);
    }

    //为应用绑定平台支持的服务类型
    @Override
    @Transactional
    public void bindPlatformChannelForApp(String appId, String platformChannelCodes) throws BusinessException {
        // AppPlatformChannel appPlatformChannel = appPlatformChannelMapper.selectOne(new LambdaQueryWrapper<AppPlatformChannel>()
        //         .eq(AppPlatformChannel::getAppId, appId)
        //         .eq(AppPlatformChannel::getPlatformChannel, platformChannelCodes));
        int count = this.queryAppBindPlatformChannel(appId, platformChannelCodes);
        if(count<=0){
            AppPlatformChannel appPlatformChannel = new AppPlatformChannel();
            appPlatformChannel.setAppId(appId);
            appPlatformChannel.setPlatformChannel(platformChannelCodes);
            appPlatformChannelMapper.insert(appPlatformChannel);
        }

    }

    //查询是否绑定了平台的某个服务类型
    @Override
    public int queryAppBindPlatformChannel(String appId, String platformChannel) throws BusinessException {
        int count = appPlatformChannelMapper.selectCount(new QueryWrapper<AppPlatformChannel>().lambda()
                .eq(AppPlatformChannel::getAppId, appId)
                .eq(AppPlatformChannel::getPlatformChannel, platformChannel));
        if (count>0){
            return 1;
        }else {
            return 0;
        }
    }

    //根据平台类型获取支付渠道列表
    @Override
    public List<PayChannelDTO> queryPayChannelByPlatformChannel(String platformChannelCode) throws BusinessException {

        return platformChannelMapper.selectPayChannelByPlatformChannel(platformChannelCode);
    }

    // 保存支付渠道参数
    @Override
    public void savePayChannelParam(PayChannelParamDTO payChannelParamDTO) throws BusinessException {
        if(payChannelParamDTO == null
                || StringUtils.isEmpty(payChannelParamDTO.getAppId())
                ||payChannelParamDTO.getMerchantId() == null
                ||payChannelParamDTO.getMerchantId() == 0
                || StringUtils.isBlank(payChannelParamDTO.getPlatformChannelCode())
        ){
            BusinessCast.cast(CommonErrorCode.E_200209);
        }
        Long appPlatformChannelId = this.selectIdByAppIDAndPlatformChannel(payChannelParamDTO.getAppId(), payChannelParamDTO.getPlatformChannelCode());

        PayChannelParam payChannelParam =  payChannelParamMapper.selectOne(new LambdaQueryWrapper<PayChannelParam>()
                .eq(PayChannelParam::getAppPlatformChannelId, appPlatformChannelId)
                .eq(PayChannelParam::getPayChannel, payChannelParamDTO.getPayChannel()));
        if(payChannelParam!=null){
            BeanUtils.copyProperties(payChannelParamDTO,payChannelParam);
            // payChannelParam.setChannelName(payChannelParamDTO.getChannelName());
            // payChannelParam.setParam(payChannelParamDTO.getParam());
            payChannelParamMapper.updateById(payChannelParam);
        }else {
            PayChannelParam entity = PayChannelParamConvert.INSTANCE.dto2entity(payChannelParamDTO);
            entity.setId(null);
            entity.setAppPlatformChannelId(appPlatformChannelId);
            payChannelParamMapper.insert(entity);
        }

        try {

            this.updateCache(payChannelParamDTO.getAppId(),payChannelParamDTO.getPlatformChannelCode());
        }catch (Exception e){
            log.error("把支付参数放入Redis缓存异常：{}"+e.getMessage());
        }
        //更新缓存

    }

    private void updateCache(String appId, String platformChannelCode) {
        // 处理Redis缓存
        // 1.构建key
        String redisKey = RedisUtil.keyBuilder(appId,platformChannelCode);
        // 2.查询redis,检查key是否存在
        if (cache.exists(redisKey)) {//存在，则清除
            //删除原有缓存
            cache.del(redisKey);
        }
        List<PayChannelParamDTO> paramDTOS =
                queryPayChannelParamByAppAndPlatform(appId,platformChannelCode);
        if (paramDTOS != null) {
            //存入缓存
            cache.set(redisKey, JSON.toJSON(paramDTOS).toString());
        }
    }

    //根据appid和服务类型查询应用与服务类型绑定id
    private Long selectIdByAppIDAndPlatformChannel(String appId, String platformChannel) throws BusinessException {
        AppPlatformChannel appPlatformChannel = appPlatformChannelMapper.selectOne(new LambdaQueryWrapper<AppPlatformChannel>()
                .eq(AppPlatformChannel::getAppId, appId)
                .eq(AppPlatformChannel::getPlatformChannel, platformChannel));
        if(appPlatformChannel == null){
            BusinessCast.cast(CommonErrorCode.E_200210);
        }
        return appPlatformChannel.getId();
    }

    //根据应用和服务类型查询支付渠道参数列表     结果可能是多个(支付宝param 微信param)
    @Override
    public List<PayChannelParamDTO> queryPayChannelParamByAppAndPlatform(String appId, String platformChannel) throws BusinessException {
        // 先从redis查询，如果有则返回,从缓存查询
        // 1.key的构建 如：SJ_PAY_PARAM:b910da455bc84514b324656e1088320b:huimin_c2b
        // String redisKey = RedisUtil.keyBuilder(appId, platformChannel);
        // // 是否有缓存
        // if(cache.exists(redisKey)){
        //     String PayChannelParamDTO_String = cache.get(redisKey);
        //     List<PayChannelParamDTO> payChannelParamDTOS = JSON.parseArray(PayChannelParamDTO_String, PayChannelParamDTO.class);
        //     return payChannelParamDTOS;
        // }
        String redisKey = RedisUtil.keyBuilder(appId, platformChannel);
        try {
            String params = cache.get(redisKey);
            if(!StringUtils.isEmpty(params)){
                List<PayChannelParamDTO> payChannelParamDTOS = JSON.parseArray(params, PayChannelParamDTO.class);
                return payChannelParamDTOS;
            }
        }catch (Exception e){
            log.error("查询redis库异常：{}"+e.getMessage());
        }

        // 如果没有的话那就去数据库查，查到了就存到Redis中
        Long id = this.selectIdByAppIDAndPlatformChannel(appId, platformChannel);
        List<PayChannelParam> payChannelParams = payChannelParamMapper.selectList(new QueryWrapper<PayChannelParam>().lambda()
                .eq(PayChannelParam::getAppPlatformChannelId, id));
        List<PayChannelParamDTO> payChannelParamDTOSDB = PayChannelParamConvert.INSTANCE.listentity2listdto(payChannelParams);

        //this.updateCache(appId,platformChannel);

        try {
            cache.set(redisKey,JSON.toJSON(payChannelParamDTOSDB).toString());
        }catch (Exception e){
            log.error("把支付参数放入Redis缓存异常：{}"+e.getMessage());
        }
        return payChannelParamDTOSDB;
    }

    //获取指定应用指定服务类型下所包含的某个原始支付参数
    @Override
    public PayChannelParamDTO queryParamByAppPlatformAndPayChannel(String appId, String platformChannel, String payChannel) throws BusinessException {
        Long id = this.selectIdByAppIDAndPlatformChannel(appId, platformChannel);
        PayChannelParam payChannelParam = payChannelParamMapper.selectOne(new LambdaQueryWrapper<PayChannelParam>()
                .eq(PayChannelParam::getAppPlatformChannelId, id)
                .eq(PayChannelParam::getPayChannel, payChannel));
        return PayChannelParamConvert.INSTANCE.entity2dto(payChannelParam);
    }


}
